﻿/*
 * This file is part of MonoStrategy.
 *
 * Copyright (C) 2010-2011 Christoph Husse
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors: 
 *      # Christoph Husse
 * 
 * Also checkout our homepage: http://monostrategy.codeplex.com/
 */
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.Serialization;

namespace MonoStrategy
{
    [ObfuscationAttribute(Feature = "renaming", ApplyToMembers = true)]
    public class Template
    {
        private static XmlSerializer m_Serializer = new XmlSerializer(typeof(List<Control>));

        private Control[] m_Children;
        private String m_XMLString;
        private XMLGUILayout m_Layout;

        [XmlAttribute]
        public String Name { get; set; }

        [XmlElement(typeof(Control))]
        [XmlElement(typeof(Image))]
        [XmlElement(typeof(Frame))]
        [XmlElement(typeof(Button))]
        [XmlElement(typeof(ListBox))]
        [XmlElement(typeof(TabButton))]
        [XmlElement(typeof(RadioButton))]
        [XmlElement(typeof(Label))]
        public List<Control> XMLChildren;

        public virtual void XMLPostProcess(XMLGUILayout inLayout)
        {
            m_Layout = inLayout;

            if (XMLChildren != null)
            {
                MemoryStream stream = new MemoryStream();

                lock (m_Serializer)
                {
                    m_Serializer.Serialize(stream, XMLChildren);

                    m_XMLString = Encoding.UTF8.GetString(stream.ToArray());
                }

                m_Children = new Control[XMLChildren.Count];

                for (int i = 0; i < m_Children.Length; i++)
                {
                    var child = (Control)XMLChildren[i];

                    child.XMLPostProcess(inLayout);

                    m_Children[i] = child;
                }

                XMLChildren = null;
            }
        }

        public void Instantiate(out List<Control> outChilds, out List<Control> outPresenters, params Object[] inParams)
        {
            // parameterize template XML
            String paramXML = m_XMLString;

            for (int i = 0; i < inParams.Length; i++)
            {
                paramXML = paramXML.Replace("{" + i + "}", inParams[i].ToString());
            }

            lock (m_Serializer)
            {
                MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(paramXML));
                outChilds = (List<Control>)m_Serializer.Deserialize(stream);
            }

            foreach(var child in outChilds)
            {
                child.XMLPostProcess(m_Layout);
            }

            // collect presenters
            outPresenters = new List<Control>();

            CollectPresenters(outChilds, outPresenters);
        }

        private void CollectPresenters(IEnumerable<Control> inChilds, List<Control> outPresenters)
        {
            foreach (var child in inChilds)
            {
                if (child is ContentPresenter)
                {
                    outPresenters.Add(child as ContentPresenter);
                }
                else
                {
                    CollectPresenters(child.Children, outPresenters);
                }
            }
        }
    }
}
